#include "stdafx.h"
#include "CrashHandler.h"

#include <float.h>
void sigfpe_test()
{
    // Code taken from http://www.devx.com/cplus/Article/34993/1954

    //Set the x86 floating-point control word according to what
    //exceptions you want to trap. 
    _clearfp(); //Always call _clearfp before setting the control
    //word
    //Because the second parameter in the following call is 0, it
    //only returns the floating-point control word
    unsigned int cw;
    _controlfp_s(&cw, 0, 0); //Get the default control
    //word
    //Set the exception masks off for exceptions that you want to
    //trap.  When a mask bit is set, the corresponding floating-point
    //exception is //blocked from being generating.
    cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE |
        EM_DENORMAL | EM_INVALID);
    //For any bit in the second parameter (mask) that is 1, the 
    //corresponding bit in the first parameter is used to update
    //the control word.  
    unsigned int cwOriginal;
    _controlfp_s(&cwOriginal, cw, MCW_EM); //Set it.
    //MCW_EM is defined in float.h.
    //Restore the original value when done:
    //_controlfp(cwOriginal, MCW_EM);

    // Divide by zero

    float a = 1;
    float b = 0;
    float c = a / b;
    c;
}

#define BIG_NUMBER 0x1fffffff
#pragma warning(disable: 4717) // avoid C4717 warning
int RecurseAlloc()
{
    int *pi = new int[BIG_NUMBER];
    pi;
    RecurseAlloc();
    return 0;
}

class CDerived;
class CBase
{
public:
    CBase(CDerived *derived) : m_pDerived(derived) {};
    ~CBase();
    virtual void function(void) = 0;

    CDerived * m_pDerived;
};

#pragma warning(disable:4355)
class CDerived : public CBase
{
public:
    CDerived() : CBase(this) {};   // C4355
    virtual void function(void) {};
};

CBase::~CBase()
{
    m_pDerived->function();
}

void main()
{
    CCrashHandler ch;
    ch.SetProcessExceptionHandlers();
    ch.SetThreadExceptionHandlers();

    printf("Choose an exception type:\n");
    printf("0 - SEH exception\n");
    printf("1 - terminate\n");
    printf("2 - unexpected\n");
    printf("3 - pure virtual method call\n");
    printf("4 - invalid parameter\n");
    printf("5 - new operator fault\n");
    printf("6 - SIGABRT\n");
    printf("7 - SIGFPE\n");
    printf("8 - SIGILL\n");
    printf("9 - SIGINT\n");
    printf("10 - SIGSEGV\n");
    printf("11 - SIGTERM\n");
    printf("12 - RaiseException\n");
    printf("13 - throw C++ typed exception\n");
    printf("Your choice >  ");

    int ExceptionType = 0;
    scanf_s("%d", &ExceptionType);

    switch (ExceptionType)
    {
    case 0: // SEH
    {
        // Access violation
        int *p = 0;
#pragma warning(disable : 6011)   // warning C6011: Dereferencing NULL pointer 'p'
        *p = 0;
#pragma warning(default : 6011)   
    }
    break;
    case 1: // terminate
    {
        // Call terminate
        terminate();
    }
    break;
    case 2: // unexpected
    {
        // Call unexpected
        unexpected();
    }
    break;
    case 3: // pure virtual method call
    {
        // pure virtual method call
        CDerived derived;
    }
    break;
    case 4: // invalid parameter
    {
        char* formatString;
        // Call printf_s with invalid parameters.
        formatString = NULL;
#pragma warning(disable : 6387)   // warning C6387: 'argument 1' might be '0': this does not adhere to the specification for the function 'printf'
        printf(formatString);
#pragma warning(default : 6387)   

    }
    break;
    case 5: // new operator fault
    {
        // Cause memory allocation error
        RecurseAlloc();
    }
    break;
    case 6: // SIGABRT 
    {
        // Call abort
        abort();
    }
    break;
    case 7: // SIGFPE
    {
        // floating point exception ( /fp:except compiler option)
        sigfpe_test();
    }
    break;
    case 8: // SIGILL 
    {
        raise(SIGILL);
    }
    break;
    case 9: // SIGINT 
    {
        raise(SIGINT);
    }
    break;
    case 10: // SIGSEGV 
    {
        raise(SIGSEGV);
    }
    break;
    case 11: // SIGTERM
    {
        raise(SIGTERM);
    }
    break;
    case 12: // RaiseException 
    {
        // Raise noncontinuable software exception
        RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL);
    }
    break;
    case 13: // throw 
    {
        // Throw typed C++ exception.
        throw 13;
    }
    break;
    default:
    {
        printf("Unknown exception type specified.");
        _getch();
    }
    break;
    }

}


